<template>
  <q-page class="q-pa-md wrapBox" style="padding:0;" v-loading="loading">
    <TransitionGroup name="leftInto">
      <div style="padding-top: 10px;" v-if="showAnimat">
        <div class="row bg-white headerBox" style="padding: 5px;">
          <div class="col-md-4  textColor">
            <el-button  @click="$router.push({ name: 'model-manage', params: { project_id: projectId } });dataSetStore().setMenuOpen(4)" plain >返回</el-button>
          </div>
          <div class="col-md-4 offset-md-4 btnBox">
            <div class="row">
              <div class="col" style="text-align: right;">
                <el-button
                  v-if="userStatus"
                  type="primary"
                  :disabled="detailData.status == 'success' ? false : true"
                  @click="createModel">创建模型</el-button>
                <el-button
                  type="primary"
                  plain
                  @click="toPage"
                  :disabled="detailData.status == 'success' || detailData.status == 'fail' ? false : true"
                  style="background-color: #fff;color: #1b5bd8">克隆</el-button>
<!--                <el-button-->
<!--                  v-if="userStatus"-->
<!--                  type="primary"-->
<!--                  :disabled="detailData.status == 'fail' ? false : true"-->
<!--                  plain-->
<!--                  @click="restartRunsFun()">重启</el-button>-->
<!--                <el-button-->
<!--                  v-if="userStatus"-->
<!--                  type="danger" :disabled="detailData.status == 'running' ? false : true" plain-->
<!--                  @click="detailData.status == 'running' ? stopRunsFun() : ''">停止</el-button>-->
              </div>
            </div>
          </div>
        </div>
        <div class="row contentBox textColor">
          <div class="col bg-white col-3 ">
            <div class="showData">
              <div class="row">
                <div class="col col-3">作业状态：</div>
                <div class="col">
                  <div>
                    <el-image :src="jobStatusIcon(detailData.status)" style="width: 25px; margin-top: 2px" fit />
                  </div>
                  <div>{{ returnToJobStatus(detailData.status) }}</div>
                </div>
              </div>
              <div class="row">
                <div class="col col-3">创建时间：</div>
                <div class="col">{{ detailData.create_at }}</div>
              </div>
              <div class="row" v-if="detailData.finish_at == null && detailData.run_at != null">
                <div class="col col-3">运行时间：</div>
                <div class="col">{{ detailData.run_at }}</div>
              </div>
              <div class="row" v-if="detailData.finish_at != null">
                <div class="col col-3">完成时间：</div>
                <div class="col">{{ detailData.finish_at }}</div>
              </div>
              <div class="row">
                <div class="col col-3">描述：</div>
                <div class="col">{{ detailData.description }}</div>
              </div>
              <div class="hrBox"></div>
              <div style="font-size: 16px;line-height: 24px;font-weight: 600;margin-bottom: 10px">来源</div>
              <div class="row">
                <div class="col col-3">算法名称：</div>
                <div class="col">{{ detailData.model_title }}</div>
              </div>
              <div class="hrBox"></div>
              <div class="row">
                <div class="col col-3">计算资源：</div>
                <div class="col">
                  CPU: {{ detailData.cpu }} 核<br>
                  GPU: {{ detailData.gpu }} 核<br>
                  内存：{{ detailData.memory }} M</div>
              </div>
              <div class="row">
                <div class="col col-3">超参：</div>
                <div class="col"></div>
              </div>
              <div class="row">
                <el-table :data="showArr" style="width: 100%"
                  :header-cell-style="{ background: '#F9F9F9', color: '#333333' }">
                  <el-table-column prop="title" label="名称" />
                  <el-table-column prop="value" label="值" />
                  <template #empty>
                    <div>暂无超参数据</div>
                  </template>
                </el-table>
              </div>
            </div>
          </div>
          <div class="col bg-grey-3">
            <div class="row">
              <div style="width: 20px;background-color: #F9F9F9"></div>
              <div class="col bg-white" style="min-height: 750px;">
                <div class="showData">
                  <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect"
                    style="border-bottom: 1px dashed #ccc;margin-bottom: 20px;user-select: none;">
                    <el-menu-item style="margin-right: 30px;" index="1">事件</el-menu-item>
                    <el-menu-item style="margin-right: 30px;" index="2">日志</el-menu-item>
                    <!-- 资源占用情况内容不清晰，暂时不显示 -->
                    <!-- <el-menu-item style="margin-right: 30px;" index="3">资源占用情况</el-menu-item> -->
                    <el-menu-item style="margin-right: 30px;" index="4">评估结果</el-menu-item>
                  </el-menu>
                </div>
                <div style="padding:0 16px;">
                  <div class="row" v-if="chooseNumber == '1'">
                    <el-table :data="eventData.results" style="width: 100%"
                      :header-cell-style="{ background: '#F9F9F9', color: '#333333' }">
                      <el-table-column prop="title" label="事件类型">
                        <template #default="scope">
                          <div v-if="scope.row.type == 'normal'">
                            <el-icon style="color:#87e226;vertical-align: middle;margin-right: 5px;">
                              <CircleCheckFilled />
                            </el-icon>
                            正常
                          </div>
                          <div v-if="scope.row.type == 'exception'">
                            <el-icon v-if="scope.row.type == 'exception'"
                              style="color:#ffea00;vertical-align: middle;margin-right: 5px;">
                              <InfoFilled />
                            </el-icon>
                            告警
                          </div>
                          <div v-if="scope.row.type == 'warning'">
                            <el-icon v-if="scope.row.type == 'warning'"
                              style="color:#ff0c0c;vertical-align: middle;margin-right: 5px;">
                              <WarningFilled />
                            </el-icon>
                            异常
                          </div>
                        </template>
                      </el-table-column>
                      <el-table-column prop="message" label="事件信息" />
                      <el-table-column prop="timestamp" label="事件发生时间" />
                    </el-table>
                    <div class="row" style="width: 100%; justify-content: end;margin-top: 20px;"
                      v-if="eventData.results.length > 0">
                      <el-pagination background layout="total, prev, pager, next" :total="10" />
                    </div>
                  </div>
                  <div v-if="chooseNumber == '2'">
                    <div
                      style="height: 40px;line-height: 40px;background: #eee;border-radius: 1px;text-align: right;padding-right: 10px;position:relative;">
                      <div style="position:absolute;left:5px;cursor:pointer;color:#3d5ce4;" @click="getLog">
                        <el-icon class="primary" style="vertical-align:middle;margin: -2px 2px 0 5px;">
                          <Refresh />
                        </el-icon>刷新
                      </div>
                      当前日志文件下载
                      <el-icon style="vertical-align: middle;margin-top: -2px;font-size: 20px;cursor: pointer;"
                        @click="showNoDataTextState ? '' : downloadLog(logData, 'log')">
                        <Download />
                      </el-icon>
                    </div>
                    <div style="max-height: 600px;">
                      <div v-if="boxLoadState && !showNoDataTextState" style="position:relative;height:200px;">
                        <box-loading></box-loading>
                      </div>
                      <div v-if="!boxLoadState && !showNoDataTextState" class="logBox" v-html="logData"></div>
                      <div v-if="showNoDataTextState" style="color:#aaa;margin:20px auto;text-align:center;">
                        {{ showNoDataText }}</div>
                    </div>
                  </div>
                  <div v-if="chooseNumber == '3'">
                    <chart-line :chartOption="chartOption2" :chartSize="chastSize2"></chart-line>
                  </div>
                  <div v-if="chooseNumber == '4'">
                    <div style="padding: 10px;">
                      <el-table :data="assessData" stripe style="width: 100%;margin: 0 auto;;"
                        :header-cell-style="{ background: '#f6f6f6', color: '#333333' }">
                        <el-table-column prop="title" label="名称" />
                        <el-table-column prop="value" label="数据" />
                        <template #empty>
                          <div>暂无数据</div>
                        </template>
                      </el-table>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!--创建模型版本 start-->
        <el-dialog v-model="modelDialogShow" :show-close="false" width="500px" :close-on-click-modal="false">
          <template #header="{ }">
            <div style="display: flex;justify-content:space-between;margin-top: 10px">
              <div style="display:flex;">
            <span style="
            margin-left: 10px;color: #1D1D1D;font-weight: bold;letter-spacing: 1px">创建模型</span>
              </div>
            </div>
          </template>
          <el-form ref="modelFormRef" :model="modelForm" :rules="modelRules" label-width="140px" status-icon>
            <el-form-item label="模型名称：" prop="title">
              <el-input v-model.trim="modelForm.title" style="font-size: 14px" placeholder="请选择模型名称" maxlength="25" show-word-limit />
            </el-form-item>
            <el-form-item label="版本：" prop="version_number">
              <el-input v-model="modelForm.version_number" placeholder="例: 0.0.1" />
            </el-form-item>
            <el-form-item label="描述：">
              <el-input type="textarea" :rows="3" v-model="modelForm.description" />
            </el-form-item>
            <el-form-item label="选择算法：" prop="modelId">
              <el-select disabled v-model.trim="modelForm.modelId" placeholder="请选择算法">
                <el-option v-for="item in allAlg" :key="item.title" :label="item.title" :value="item.id" @click="chooseAlg" />
              </el-select>
            </el-form-item>
            <el-form-item label="选择训练作业:" prop="model_run_id">
              <el-select disabled v-model="modelForm.model_run_id" placeholder="请选择训练任务">
                <el-option v-for="item in modelRunsData" :key="item.id" :label="item.title" :value="item.id" />
              </el-select>
            </el-form-item>
            <div style="display: flex;width: 100%;border-top: 1px solid rgb(234,234,234);padding: 5px 0">
              <div
                style="flex: 1;text-align: center;line-height: 30px;cursor: pointer;margin-bottom: 0;border-right: 1px solid rgb(234, 234, 234)"
                @click="resetForm(modelFormRef)">取消</div>
              <div style="flex: 1;text-align: center;line-height: 30px;color: rgb(58,141,255);cursor: pointer;margin-bottom: 0"
                @click="submitForm(modelFormRef)">完成创建</div>
            </div>
          </el-form>
        </el-dialog>
      </div>
    </TransitionGroup>
  </q-page>
</template>

<script setup lang="ts">
import { reactive, ref, shallowRef } from "vue";
import { useRouter } from 'vue-router';
import chartLine from 'src/components/chartLine.vue';
import {
  getRunsDetail,
  getRunsDetailEvents,
  getRunsDetailLog,
  getRunsDetailMetrics,
  stopRuns,
  restartRuns,
  createModelApp,
  validateModelName, getAlgAllList, getModelAboutRuns
} from 'src/api/model'
const userStatus = JSON.parse(localStorage.getItem('user') || "{}").status;//判断用户是否是项目创建人或项目管理员
import {ElMessageBox, ElMessage, FormRules, FormInstance} from 'element-plus';
import boxLoading from 'src/components/boxLoading.vue';
const loading=ref(true)
const router = useRouter()
const projectId = router.currentRoute.value.query.project_id;
const showAnimat = ref(false)
import { modelStore } from 'src/stores/model';
import { dataSetStore } from 'src/stores/dataSet';

const chastSize2 = reactive({
  width: '100%',
  height: "365px"
})
const chartOption2 = reactive({
  tooltip: {
    axisPointer: {
      type: 'shadow', //默认为line，line直线，cross十字准星，shadow阴影
      crossStyle: {
        color: '#fff'
      }
    },
    trigger: 'axis',
  },
  grid: {
    left: '1%',
    right: '1%',
    bottom: '5%',
    top: '8%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    data: ['1min', '2min', '3min', '4min', '5min', '6min', '7min']
  },
  yAxis: {
    type: 'value',
    max: 100
  },
  series: [
    {
      name: 'GPU',
      data: [20, 30, 50, 80, 30, 40, 65],
      color: '#5087ec',
      type: 'line',
    },
    {
      name: 'CPU',
      data: [30, 30, 10, 60, 30, 30, 95],
      color: '#68bbc4',
      type: 'line',
    },
    {
      name: 'memory',
      data: [70, 85, 40, 30, 10, 60, 35],
      color: '#58a55c',
      type: 'line',
    }
  ]
})
const eventData = shallowRef({
  results: []
})
const activeIndex = ref('1')
const chooseNumber = ref('1')
const logData = ref('')
const parametersObj = shallowRef()
const parametersDefault = shallowRef()
const showArr = ref([])
const handleSelect = (key: string, keyPath: string[]) => {
  chooseNumber.value = key
  selectFun(chooseNumber.value)
}
function selectFun(num: string) {
  if (num == '1') getEvent()
  if (num == '2') getLog()
  if (num == '4') getMetrics()
}
const detailData = shallowRef({
  cpu: '',
  create_at: '',
  creator_username: '',
  description: '',
  gpu: 0,
  id: 0,
  memory: 0,
  ml_entry_point: null,
  ml_enviroment: null,
  ml_parameters: {},
  ml_project_version: null,
  ml_run_id: '',
  model_id: 0,
  model_title: '',
  status: '',
  title: '',
  run_at: '',
  finish_at: ''
})
const assessData = shallowRef(<any>[])
const boxLoadState = ref(false)
const showNoDataTextState = ref(false)
const showNoDataText = ref('');
const modelFormRef = ref(); //创建模型ref
let modelDialogShow = ref(false);//创建模型弹框
const modelForm = ref({ // 模型弹框相关数据
  title: '',
  description: '',
  version_number: '1',
  modelId: '',
  model_run_id: ''
});
const validateTitle = (rule: any, value: any, callback: any) => {
  if (!value) {
    callback(new Error('模型名称不能为空'))
    return
  }
  let params = {
    title: modelForm.value.title
  }
  validateModelName(projectId, params).then(res => {
    if (res.data.exists) {
      callback(new Error('模型名称重复'))
    }
    callback()
  }).catch(err => {
    callback(new Error('校验接口报错'))
  })
}
const modelRules = reactive<FormRules>({ //模型创建表单校验
  title: [
    { required: true, validator: validateTitle, trigger: 'blur' }
  ],
  version_number: [
    { required: true, message: '请输入版本号', trigger: 'blur' }
  ],
  modelId: [
    { required: true, message: '请选择算法', trigger: 'blur' },
  ],
  model_run_id: [
    { required: true, message: '请选择训练作业', trigger: 'blur' },
  ],
});
//存放获取所有的算法
const allAlg = shallowRef([
  {
    title: '',
    id: ''
  }
]);
//存放获取所有的训练任务
const modelRunsData = ref([])
AlgAllList();//获取所有的算法
function AlgAllList() {
  getAlgAllList(projectId).then((res: any) => {
    allAlg.value = Object.assign(res.data)
  }).catch(error => {
    console.log(error)
  })
};
//获取算法对应下的训练任务
function chooseAlg(modeId:number) {
  loading.value = true;
  getModelAboutRuns(projectId, modeId).then((res: any) => {
    loading.value = false;
    modelRunsData.value = res.data.filter((items: any) => items.status === 'success');
  }).finally(() => {
    loading.value = false;
  }).catch(error => {
    console.log(error)
  })
};
//创建模型表单重置
const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields();
  modelDialogShow.value = false;
}

//点击创建模型
const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      let params = Object.assign(modelForm.value);

      createModelApp(projectId,params).then((res: any) => {
        ElMessage.success(`创建模型成功！`);
        modelDialogShow.value = false;
        router.push({ name:'model-app', params: { project_id: projectId } })
      }).finally(() => {
        loading.value = false;
        formEl.resetFields();
      }).catch((error: any) => {
        ElMessage.success(`模型创建失败,提示${error.data}！`)
      })
    } else {
      console.log('error submit!', fields)
    }
  })
}


getData()
function getData() {
  loading.value=true
  getRunsDetail(projectId, modelStore().model_id, modelStore().runs_id).then((res: any) => {
    showAnimat.value = true;
    detailData.value = res.data;
    modelForm.value.modelId = res.data.model_id;
    modelForm.value.model_run_id = res.data.id;
    chooseAlg(res.data.model_id);
    // modelForm.value.title
    parametersObj.value = Object.keys(res.data.ml_parameters)
    parametersDefault.value = Object.values(res.data.ml_parameters)
    showArr.value = []
    showArr.value = parametersObj.value.map((item: any, index: any) => {
      let obj = {
        title: item,
        value: parametersDefault.value[index]
      }
      return obj
    })
    loading.value=false
  })
}
//返回训练状态图标
function jobStatusIcon(val:any){
  switch(val) {
    case 'fail':
      return '/svgs/JobStatus_fail.svg'
    case 'success':
      return '/svgs/JobStatus_success.svg'
    case 'running':
      return '/svgs/JobStatus_running.svg'
    case 'stopping':
      return '/svgs/JobStatus_stopping.svg'
    case 'waiting':
      return '/svgs/JobStatus_waiting.svg'
  }
}
//返回训练状态
function returnToJobStatus(val:any){
  switch(val) {
    case 'fail':
      return '失败'
    case 'success':
      return '已完成'
    case 'running':
      return '运行中'
    case 'stopping':
      return '停止'
    case 'waiting':
      return '等待中'
  }
}
//点击克隆跳转到创建训练作业页面
function toPage(){
  router.push({ name: 'model-manage-create', params: { project_id: projectId } })
}
function createModel() {
  modelDialogShow.value = true;
}
getEvent()
// 获取事件数据
function getEvent() {
  getRunsDetailEvents(projectId, modelStore().runs_id).then((res: any) => {
    eventData.value = res.data
  }).catch(error => {
    console.log(error)
  })
}
// 获取日志数据
function getLog() {
  boxLoadState.value = true
  showNoDataTextState.value = false
  logData.value = ''
  let statusStr = ''
  if (detailData.value.status == 'success' || detailData.value.status == 'running') {
    statusStr = 'output.log'
  } else {
    statusStr = 'error.log'
  }
  getRunsDetailLog(projectId, modelStore().runs_id, statusStr).then((res: any) => {
    logData.value = res.data.replace(/\r\n/g, '<br>')
    boxLoadState.value = false
  }).catch(error => {
    if (error.response.status >= 500) showNoDataText.value = '获取日志失败'
    if (error.response.status == 404) showNoDataText.value = '暂无日志'
    showNoDataTextState.value = true
    boxLoadState.value = false
  })
}
function getMetrics() {
  getRunsDetailMetrics(projectId, modelStore().runs_id).then((res: any) => {
    assessData.value = filterType(res.data)
  }).catch(error => {
    console.log(error)
  })
}
// 解析评估结果数据
const filterType = (data: any) => {
  let filterTitle = Object.keys(data)
  let filterVakue = Object.values(data)
  let newArr = filterTitle.map((item, index) => {
    let obj = {
      title: item,
      value: filterVakue[index]
    }
    return obj
  })
  return newArr
}

// 下载日志数据
function downloadLog(data: any, name: string) {
  ElMessageBox.confirm('确定下载该日志数据吗？', '日志下载', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'success'
  }).then(() => {
    let urlObject = window.URL || window.webkitURL || window;
    let export_blob = new Blob([data]);
    let save_link = document.createElement("a")
    save_link.href = urlObject.createObjectURL(export_blob);
    save_link.download = name;
    save_link.click();
  })
}
// 不可点击的按钮提示
// function tipFun(str:string){
//   let tipStr=''
//   if(str=='创建') tipStr='该训练任务正在执行中,请等待'
//   if(str=='重启') tipStr='该训练任务正在执行中,不可重启!'
//   if(str=='停止') tipStr='该训练任务已完成,不可停止!'
//   ElMessage.warning(tipStr)
// }
// 停止训练任务
function stopRunsFun() {
  ElMessageBox.confirm('确定停止该训练任务吗？', '停止训练任务', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    stopRuns(projectId, modelStore().runs_id).then(() => {
      ElMessage.success('停止训练成功！')
      getData()
      selectFun(chooseNumber.value)
    }).finally(() => {
      loading.value = false
    })
  })
}
// 重启任务
function restartRunsFun() {
  ElMessageBox.confirm('确定重启该训练任务吗？', '重启训练任务', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    restartRuns(projectId, modelStore().runs_id).then(() => {
      ElMessageBox.alert('重启训练任务成功!', '提示', {
        confirmButtonText: 'ok',
        autofocus: false
      }).then(() => {
        getData()
        selectFun(chooseNumber.value)
      })
    }).finally(() => {
      loading.value = false
    })
  })
}

</script>

<style scoped lang="scss">
//创建模型弹框去掉边框
:deep(.el-dialog__body){
  padding: 0 20px!important;
}
.wrapBox {
  background-color: #F6F8FA!important;
}
.headerBox {
  height: 50px;
  line-height: 40px;
  margin-bottom: 20px;

  .backPage {
    .el-icon {
      margin-left: 10px;
    }

    cursor: pointer;

    i {
      font-style: initial;
      display: inline-block;
      line-height: 38px;
    }

    &::v-deep .el-icon svg {
      margin: -2px;
    }
  }

  .btnBox {
    .el-button {
      margin-right: 10px;
    }
  }
}

.contentBox {
  .col {
    &:first-child {
      border-radius: 0 4px 0 0;
    }

    &:last-child {
      border-radius: 4px 0 0 0;
    }
  }

  .showData {
    padding: 16px 16px 0 16px;

    .row {
      margin: 0 0 20px 0;
    }
  }

  .hrBox {
    width: 100%;
    border-bottom: 1px solid #E8E8E8;;
    margin: 10px 0;
  }
}

.logBox {
  max-height: 600px;
  overflow-y: auto;
  padding: 10px;
  white-space: pre-wrap;
  word-wrap: break-word;
  box-shadow: 0 2px 4px 1px #e9e9e9;

  &::-webkit-scrollbar {
    width: 5px;
  }

  &::-webkit-scrollbar-track {
    background: rgb(237, 237, 237);
    border-radius: 5px;
  }

  &::-webkit-scrollbar-thumb {
    background: #3D5CE4;
    border-radius: 5px;
  }
}
:deep(.el-menu--horizontal > .el-menu-item){
  margin: 0!important;
  height: 36px!important;
  padding: 10px!important;
  color: #333;
  font-weight: 500;
  border-bottom: none;
}
:deep(.el-menu--horizontal > .el-menu-item.is-active){
  margin: 10px;
  padding: 10px!important;
  background-color: #EDEFFE;
  color: #3D5CE4;
  font-weight: 500;
  border-bottom: none;
}
</style>
